﻿using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data;
using System.Collections;
namespace Com.Dal.Cms
{
    /// <summary>
    /// 数据库访问抽象基类  
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class RepositoryBase<T> : IRepository<T> where T : class,new()
    {
        private DbContext contexts = null;
        public RepositoryBase()
        {
        }
        public void Init(Object entityContainer)
        {
            if (entityContainer != null)
            {
                if (this.contexts == null)
                {
                    this.contexts = entityContainer as DbContext;
                }
            }
        }
        /// <summary>
        /// 为支持多数据库,所以子类必须调用Init方法
        /// </summary>
        /// <param name="entityContainer"></param>
        public T Create()
        {
            return contexts.Set<T>().Create();
        }
        public T Insert(T entity)
        {
            var result = contexts.Set<T>().Add(entity);
            contexts.SaveChanges();
            return entity;
        }
        public int Update(T entity)
        {
            int affect = 0;
            contexts.Entry<T>(entity).GetValidationResult();
            if (contexts.Entry<T>(entity).State == EntityState.Modified)
            {
                affect = contexts.SaveChanges();
            }
            return affect;
        }
        public int Delete(T entity)
        {
            var result = contexts.Set<T>().Remove(entity);
            return contexts.SaveChanges();
        }
        public int Delete(String sql, params Object[] ps)
        {
            var result = contexts.Database.ExecuteSqlCommand(sql, ps);
            return result;
        }
        /// <summary>
        /// 查询一条数据
        /// </summary>
        /// <param name="ps">键值集合</param>
        /// <returns>T</returns>
        public T Find(params Object[] ps)
        {
            var result = contexts.Set<T>().Find(ps);
            return result;
        }
        public T Find(Expression<Func<T, bool>> conditions) {
            return contexts.Set<T>().Where(conditions).First();
        }
        public ICollection<T> FindList(String sql, params Object[] ps)
        {
            var result = contexts.Database.SqlQuery<T>(sql, ps);
            sql = result.ToString();
            return result.ToList();
        }
        public ICollection<T> FindList(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, Int32>> orderBy)
        {
            pageIndex = pageIndex < 1 ? 1 : pageIndex;
            pageSize = pageSize < 1 ? 1 : pageSize;
            int skip = (pageIndex - 1) * pageSize;
            var result = contexts.Set<T>().Where(where).OrderBy(orderBy).Skip(skip).Take(pageSize);
            return result.ToList();
        }

        public ICollection<T> FindList(int pageIndex, int pageSize, Expression<Func<T, bool>> where, Expression<Func<T, DateTime>> orderBy)
        {
            pageIndex = pageIndex < 1 ? 1 : pageIndex;
            pageSize = pageSize < 1 ? 1 : pageSize;
            int skip = (pageIndex - 1) * pageSize;
            var result = contexts.Set<T>().Where(where).OrderBy(orderBy).Skip(skip).Take(pageSize);
            return result.ToList();
        }

        public int FindCount(Expression<Func<T, bool>> where)
        {
            return contexts.Set<T>().Count(where);
        }

        public ICollection<T> FindList()
        {
            var result = contexts.Set<T>();
            return result.ToList();
        }

        public Object ExecuteSql(Type type, String sql, params Object[] ps)
        {
            var result = contexts.Database.SqlQuery(type, sql, ps);
            sql = result.ToString();
            return result;
        }
    }
}
